package wangwenjun.phase3.executor.completablefuture.demo02;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import util.ThreadUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author ChangLiang
 * @date 2020/6/26
 */
@Slf4j
public class AppV5Test {

    @Test
    @DisplayName("test CompletableFuture")
    public void test(){
        List<String> list = new ArrayList<>();
        log.warn("start");
        long start = System.currentTimeMillis();

        EsService esService = new EsService();

        String keyword = "changliang";

        CompletableFuture<Void> future = CompletableFuture.allOf(
                CompletableFuture.supplyAsync(() -> {
                    try {
                        return esService.searchQueryItems(keyword);
                    } catch (InterruptedException e) {
                        throw new RuntimeException("convent checked InterruptedException to unchecked RuntimeException");
                    }
                })
                        .exceptionally(t -> {
                            log.error(ThreadUtil.exceptionToString(t));
                            log.error("query item fails, keyword:{}", keyword);
                            throw new RuntimeException(t.getMessage());
                        })
                        .whenComplete((v, t) -> {
                            if (t == null && StringUtils.isNotEmpty(v)) {
                                list.add(v);
                            }
                        }),
                CompletableFuture.supplyAsync(() -> {
                    try {
                        return esService.searchQueryGuides(keyword);
                    } catch (InterruptedException e) {
                        throw new RuntimeException("convent checked InterruptedException to unchecked RuntimeException");
                    }
                })
                        .exceptionally(t -> {
                            log.error(ThreadUtil.exceptionToString(t));
                            log.error("query guide fails, keyword:{}", keyword);
                            throw new RuntimeException(t.getMessage());
                        })
                        .whenComplete((v, t) -> {
                            if (t == null && StringUtils.isNotEmpty(v)) {
                                list.add(v);
                            }
                        }),
                CompletableFuture.supplyAsync(() -> {
                    try {
                        return esService.getApplications(keyword);
                    } catch (InterruptedException e) {
                        throw new RuntimeException("convent checked InterruptedException to unchecked RuntimeException");
                    }
                })
                        .exceptionally(t -> {
                            log.error(ThreadUtil.exceptionToString(t));
                            log.error("query app fails, keyword:{}", keyword);
                            throw new RuntimeException(t.getMessage());
                        })
                        .whenComplete((v, t) -> {
                            if (t == null && StringUtils.isNotEmpty(v)) {
                                list.add(v);
                            }
                        }),
                CompletableFuture.supplyAsync(() -> {
                    try {
                        return esService.getAppointItems(keyword);
                    } catch (InterruptedException e) {
                        throw new RuntimeException("convent checked InterruptedException to unchecked RuntimeException");
                    }
                })
                        .exceptionally(t -> {
                            log.error(ThreadUtil.exceptionToString(t));
                            log.error("query appoint fails, keyword:{}", keyword);
                            throw new RuntimeException(t.getMessage());
                        })
                        .whenComplete((v, t) -> {
                            if (t == null && StringUtils.isNotEmpty(v)) {
                                list.add(v);
                            }
                        })
        );
        try {
            future.get(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        log.warn("full execution time consumption:{} ms", (end - start));
        log.info("result:{}", list);
    }
}
